/*	$OpenBSD: setjmp.S,v 1.2 2004/02/01 05:40:52 drahn Exp $	*/
/*	$NetBSD: setjmp.S,v 1.5 2003/04/05 23:08:51 bjh21 Exp $	*/

/*
 * Copyright (c) 1997 Mark Brinicombe
 * Copyright (c) 2010 Android Open Source Project.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by Mark Brinicombe
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <machine/asm.h>
#include <machine/setjmp.h>
#include <machine/cpu-features.h>

/*
 * C library -- setjmp, longjmp
 *
 *	longjmp(a,v)
 * will generate a "return(v)" from the last call to
 *	setjmp(a)
 * by restoring registers from the stack.
 * The previous signal state is restored.
 */

 #ifndef __clang__

ENTRY(setjmp)
  bic     a1, #0xC0000000
  stmea   a1!, { v1-v5, v7, fp, ip, sp, lr }
  bic     a1, #0xC0000000
  vstm    a1, { d8-d15 }
  mov     a1, #0
	sfi_bx  lr
END(setjmp)


ENTRY(longjmp)
  bic     a1, #0xC0000000
  ldmfd   a1!, { v1-v5, v7, fp, ip, sp, lr }
  bic     sp, #0xC0000000
  nop
  bic     a1, #0xC0000000
  vldm    a1, {d8-d15}
  cmp     a2, #0
  moveq   a1, #1
  sfi_bx  lr
END(longjmp)

#else
#define NACL_BLOCK_SHIFT        4
#define NACL_DATA_FLOW_MASK     0xC0000000
#define NACL_CONTROL_FLOW_MASK  0xC000000F

    .text
    .align NACL_BLOCK_SHIFT
    .globl setjmp

/* int setjmp(jmp_buf env) */
setjmp:
    bic     r0, r0, #NACL_DATA_FLOW_MASK
    stmia   r0!, {r4, r5, r6, r7, r8, r10, r11, r12, sp, lr}
    bic     r0, r0, #NACL_DATA_FLOW_MASK
    vstmia  r0!, {d8-d15}

    mov     r0, #0
    bic     lr, lr, #NACL_CONTROL_FLOW_MASK
    bx      lr


    .text
    .align NACL_BLOCK_SHIFT
    .globl longjmp

/* void longjmp(jmp_buf env, int val) */
longjmp:
    bic     r0, r0, #NACL_DATA_FLOW_MASK
    ldmia   r0!, {r4, r5, r6, r7, r8, r10, r11, r12, sp, lr}
    bic     sp, sp, #NACL_DATA_FLOW_MASK
    nop

    bic     r0, r0, #NACL_DATA_FLOW_MASK
    vldmia  r0!, {d8-d15}
    /* Return the result argument if nonzero or 1 otherwise */
    /* Note: move updates condition codes */
    movs    r0, r1
    moveq   r0, #1

    bic     lr, lr, #NACL_CONTROL_FLOW_MASK
    bx      lr

#endif